package org.korifey.ffbdd.chess;

import java.util.ArrayList;
import java.util.List;

import org.korifey.ffbdd.chess.Figure.Pawn;


public class Position {
	public static final int BOARDSIZE = 8;
	
	List<Figure> white;
	List<Figure> black;
	
	boolean whiteMove;
	Move lastMove;
	Figure[][] boardMatrix;
	
	
	public Position(List<Figure> white, List<Figure> black, boolean whiteMove,
			Move lastMove) {
		super();
		this.white = white;
		this.black = black;
		this.whiteMove = whiteMove;
		this.lastMove = lastMove;
		this.boardMatrix = generateBoardMatrix();
	}


	public boolean isCheckmate() {
		for (Figure f: black) {
			if (f instanceof Figure.King) {
				if (f.availableMoves(this).size() == 0 && underBeat(f.getCoord())) return true;
				else return false;
			}
		}
		throw new RuntimeException("No black king");
	}
	

	private boolean underBeat(Coord coord) {
		for (Figure f: white) {
			if (f.canEat(this, coord)) return true; 
		}
		return false;
	}


	public List<Position> nextPossiblePositions() {
		List<Position> res = new ArrayList<Position>();
		if (whiteMove) {
			for (Figure f: white) {
				
				List<Coord> l = f.availableMoves(this);
				for (Coord c: l) {
					
					//Populating white figures
					List<Figure> nwhite = new ArrayList<Figure>(white);
					nwhite.remove(f);
					Figure nf = (Figure)f.clone();
					nf.setCoord(c);
					nwhite.add(nf);
					ACTION action = ACTION.MOVE;
					
					List<Figure> nblack = new ArrayList<Figure>(black);
 					for (Figure b: black) {
						if (b.getCoord().equals(c) || beatOnPassage(f, c, b)) {
							nblack.remove(b);
							action = ACTION.EAT;
							break;
						}
					}
 					
 					res.add(new Position(nwhite, nblack, false, new Move(f, action, c)));
				}
				
			}
			
			
		} else {
				for (Figure f: black) {
				
				List<Coord> l = f.availableMoves(this);
				for (Coord c: l) {
					
					//Populating white figures
					List<Figure> nblack = new ArrayList<Figure>(black);
					nblack.remove(f);
					Figure nf = (Figure)f.clone();
					nf.setCoord(c);
					nblack.add(nf);
					ACTION action = ACTION.MOVE;
					
					List<Figure> nwhite = new ArrayList<Figure>(black);
 					for (Figure b: white) {
						if (b.getCoord().equals(c) || beatOnPassage(f, c, b)) {
							nwhite.remove(b);
							action = ACTION.EAT;
							break;
						}
					}
 					
 					res.add(new Position(nwhite, nblack, true, new Move(f, action, c)));
				}
				
			}
		}
		return res;
	}

	
	public boolean beatOnPassage(Figure taker, Coord takerCoord, Figure taken) {
		return  taken.getCoord().equals(lastMove.getNewPosition()) &&
				taker instanceof Pawn &&
				taken instanceof Pawn &&				
				lastMove.getFigure() instanceof Pawn &&	
				(taker.isWhite() != taken.isWhite()) &&
				Math.abs(taken.getCoord().v() - taker.getCoord().v()) == 1 &&
				taken.getCoord().h() == taker.getCoord().h() &&
				(				
				(taker.isWhite() && taken.getCoord().h() == BOARDSIZE - 4 && lastMove.getFigure().getCoord().h() == BOARDSIZE - 2) ||
				(!taker.isWhite() && taken.getCoord().h() == 3 && lastMove.getFigure().getCoord().h() == 1)				
				);
	}

	
	public Move getLastMove() {
		return lastMove;
	}
	
	
	public Figure[][] getBoardMatrix() {
		return boardMatrix;
	}


	private Figure[][] generateBoardMatrix() {
		Figure[][] res = new Figure[BOARDSIZE][BOARDSIZE];
		for (int i=0; i<BOARDSIZE; i++) {
			for (int j=0; j<BOARDSIZE; j++) {
				res[i][j] = Figure.EMPTY;
			}
		}
		
		for (Figure f: white) {
			res[f.getCoord().h()][f.getCoord().v()]  = f;
		}
		for (Figure f: black) {
			res[f.getCoord().h()][f.getCoord().v()]  = f;
		}
		return res;
	}
}
